import 'package:bruno/bruno.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:reactive_forms/reactive_forms.dart';
import 'package:yt_devops/components/brn/brn_input_text.dart';
import 'package:yt_devops/components/yt_form/props/brn_text_input_props.dart';
import 'package:yt_devops/components/yt_form/utils/form_widget_utils.dart';

import 'package:yt_devops/routers/router_path.dart';
import 'package:yt_devops/styles/styles.dart';
import 'package:yt_devops/utils/func_utils.dart';

enum ShowType { page, input }

class ReactiveBrunoTextInput<T> extends ReactiveFormField<T, String> {
  ReactiveBrunoTextInput(
      {Key? key,
      String? formControlName,
      FormControl<T>? formControl,
      Map<String, ValidationMessageFunction>? validationMessages,
      ControlValueAccessor<T, String>? valueAccessor,
      ShowErrorsFunction<T>? showErrors,
      FocusNode? focusNode,

      ////////////////////////////////////////////////////////////////////////////
      bool requiredStar = false,
      String title = '',
      dynamic Function(String)? onTextChange,
      dynamic Function(String)? onSubmit,
      double maxHeight = 200,
      double minHeight = 50,
      Color bgColor = Colors.white,
      int maxLength = 200,
      int minLines = 3,
      String? hint,
      int? maxHintLines,
      EdgeInsetsGeometry padding = EdgeInsets.zero,
      String textString = "",
      bool? autoFocus,
      TextInputAction textInputAction = TextInputAction.done,
      TextEditingController? textEditingController,
      double? borderRadius,
      Color? borderColor,
      double textLengthSize = 16,
      // 边框
      Border? border =
          const Border(bottom: BorderSide(color: Colour.dividerColor)),
      bool enabled = true,
      // 文本与在表单中的展示方式
      ShowType showType = ShowType.input})
      : super(
            key: key,
            formControl: formControl,
            formControlName: formControlName,
            valueAccessor: valueAccessor,
            validationMessages: validationMessages,
            showErrors: showErrors,
            builder: (field) {
              final effectiveDecoration =
                  Theme.of(field.context).inputDecorationTheme;

              final state = field as _ReactiveBrunoTextInputState<T>;
              state._setFocusNode(focusNode);
              String? errorText = field.errorText;

              if (showType == ShowType.input) {
                return Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      FormWidgetUtils.getHeadTitleWidget(title,
                          labelStyle: effectiveDecoration.labelStyle,
                          required: requiredStar),
                      YBrnInputText(
                        textEditingController: state._textController,
                        maxHeight: maxHeight,
                        minLines: minLines,
                        maxHintLines: maxHintLines,
                        hint: hint,
                        padding: padding,
                        autoFocus: autoFocus,
                        textInputAction: textInputAction,
                        borderRadius: borderRadius,
                        borderColor: borderColor,
                        textLengthSize: textLengthSize,
                        enabled: enabled,
                        onTextChange: (input) {
                          field.didChange(input);
                          onTextChange?.call(input);
                        },
                      ),
                      if (!FuncUtils.isEmpty(errorText))
                        Text(
                          errorText!,
                          style: TextStyles.f12.warningColorStyle,
                        ),
                      const SizedBox(
                        height: 14,
                      )
                    ]);
              } else {
                var textfield = BrnTextSelectFormItem.autoLayout(
                  title: title,
                  value: state.value,
                  layoutRatio: 0.9,
                  themeData: BrnFormItemConfig(
                      contentTextStyle: BrnTextStyle.withStyle(TextStyles.f16),
                      hintTextStyle: BrnTextStyle(
                          fontSize: 16.sp, color: Colour.hintTextColor)),
                  onTap: () {
                    Get.toNamed(RouterPath.textInputPage,
                            arguments: BrnTextInputProps(
                                title: title,
                                hint: hint,
                                requireStar: requiredStar,
                                minHeight: minHeight,
                                maxHeight: maxHeight,
                                maxLength: maxLength,
                                minLines: minLines,
                                enabled: enabled,
                                textEditingController: textEditingController,
                                textInputAction: textInputAction,
                                textLengthSize: textLengthSize,
                                textString: state.value ?? '',
                                autoFocus: autoFocus,
                                bgColor: bgColor,
                                borderColor: borderColor,
                                borderRadius: borderRadius,
                                onSubmit: onSubmit,
                                onTextChange: onTextChange))
                        ?.then((value) {
                      if (value is String && value.isNotEmpty) {
                        state.didChange(value);
                      }
                    });
                  },
                );

                return Row(
                  children: [
                    FormWidgetUtils.getStar(requiredStar),
                    Expanded(
                      child: DecoratedBox(
                          position: DecorationPosition.foreground,
                          decoration: const BoxDecoration(
                              border: Border(
                                  bottom:
                                      BorderSide(color: Colour.dividerColor))),
                          child: textfield),
                    ),
                  ],
                );
              }
            });

  @override
  ReactiveFormFieldState<T, String> createState() =>
      _ReactiveBrunoTextInputState<T>();
}

class _ReactiveBrunoTextInputState<T>
    extends ReactiveFormFieldState<T, String> {
  late TextEditingController _textController;
  FocusNode? _focusNode;
  late FocusController _focusController;

  @override
  FocusNode get focusNode => _focusNode ?? _focusController.focusNode;

  @override
  void initState() {
    super.initState();

    final initialValue = value;
    _textController = TextEditingController(
        text: initialValue == null ? '' : initialValue.toString());
  }

  @override
  void subscribeControl() {
    _registerFocusController(FocusController());
    super.subscribeControl();
  }

  @override
  void unsubscribeControl() {
    _unregisterFocusController();
    super.unsubscribeControl();
  }

  @override
  void onControlValueChanged(dynamic value) {
    final effectiveValue = (value == null) ? '' : value.toString();
    _textController.value = _textController.value.copyWith(
      text: effectiveValue,
      selection: TextSelection.collapsed(offset: effectiveValue.length),
      composing: TextRange.empty,
    );

    super.onControlValueChanged(value);
  }

  @override
  ControlValueAccessor<T, String> selectValueAccessor() {
    if (control is FormControl<int>) {
      return IntValueAccessor() as ControlValueAccessor<T, String>;
    } else if (control is FormControl<double>) {
      return DoubleValueAccessor() as ControlValueAccessor<T, String>;
    } else if (control is FormControl<DateTime>) {
      return DateTimeValueAccessor() as ControlValueAccessor<T, String>;
    } else if (control is FormControl<TimeOfDay>) {
      return TimeOfDayValueAccessor() as ControlValueAccessor<T, String>;
    }

    return super.selectValueAccessor();
  }

  void _registerFocusController(FocusController focusController) {
    _focusController = focusController;
    control.registerFocusController(focusController);
  }

  void _unregisterFocusController() {
    control.unregisterFocusController(_focusController);
    _focusController.dispose();
  }

  void _setFocusNode(FocusNode? focusNode) {
    if (_focusNode != focusNode) {
      _focusNode = focusNode;
      _unregisterFocusController();
      _registerFocusController(FocusController(focusNode: _focusNode));
    }
  }
}
